iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 27
1
Modern Web

Node JS-Back end見聞錄系列 第 27

Node.js-Backend見聞錄(26):進階實作-關於第三方登入(一)

  • 分享至 

  • xImage
  •  

Node.js-Backend見聞錄(26):進階實作-關於第三方登入(一)

前言

在進入到實作前,我們先來理解下關於OAuth的運作原理以及Facebook的第三方登入其運行過程如何。

OAuth 2.0

「OAuth 2.0是OAuth協定的下一版本,但不向下相容OAuth 1.0。OAuth 2.0關注用戶端開發者的簡易性,同時為Web應用,桌面應用和手機,和起居室裝置提供專門的認證流程。」 引用自OAuth Wiki

在介紹OAuth 2.0之前,我們要先了解為什麼會有OAuth這個標準。

    +--------+                                  +--------+
    | Client | ------ user credentials ------>  | Server |
    +--------+                                  +--------+
 
request: 傳遞使用者憑證(如:帳號跟密碼)
response: 使用者個人資料

以Client-Server架構來說,Client要提取resource owner的受保護資料(protected resource)時,要向Server端傳輸使用者憑證(使用者帳號及密碼)才可以。

小劇場
    +--------+                          +--------------------------+
    |  User  |                          | Third-party applications |
    +--------+                          |         (第三方)          |
                                        +--------------------------+
第三方跟Server說:我想要使用者的隱私資料,可以給我嗎?
Server回第三方說:可以阿,但你要先給我使用者的帳號跟密碼。
第三方跟User說:你可以給我你的帳號跟密碼嘛?因為我想要你的資料。
User跟第三方說:說給你就給你喔?
第三方:........

為了讓第三方應用程式拿到這些受保護資料(protected resource),使用者(resource owner)也要把憑證給這個第三方才行,但這樣子就會造成下述的這些問題:

  • 第三方應用程序需要儲存使用者的憑證來使用,而這些密碼通常是明文。
  • Server端需要支持密碼的認證,儘管密碼含有安全性的漏洞問題。
  • 第三方應用程式會獲得幾乎完整的使用權限,可以存取受保護資料,而使用者不能限制第三方應用程式可以拿取資料的時限,以及可以存取的資料範圍(subset)。
  • 使用者不能撤銷第三方的權限,必須藉由更改使用者密碼的方式才行。
  • 任何第三方應用程式被破解,都會導致使用者的密碼和所有受該密碼保護的資料被破解。

而OAuth為了解決這些問題,分成了四個不同的角色:

  • Resource owner:可以授權別人去存取受保護資料資料。如果這個角色是人類的話,指的就是使用者(end-user)。
  • Resource server:存取受保護資料的Server,可以根據access Token來接受取得隱私資料的request。
  • Client:代表使用者去存取受保護資料的應用程式。「client」指的並不是任何特定的實做方式,任何在server端、桌面或設備上執行的應用程式,都可稱為client。
  • Authorization server:在認證過使用者的身份,且經由使用者許可後,就會簽發access token的server。

Client分為resource owner及client(第三方),Server分成resource server及authorization server。並提出了一個概念式的OAuth處理流程:

     +--------+                               +---------------+
     |        |--(A)- Authorization Request ->|   Resource    |
     |        |                               |     Owner     |
     |        |<-(B)-- Authorization Grant ---|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(C)-- Authorization Grant -->| Authorization |
     | Client |                               |     Server    |
     |        |<-(D)----- Access Token -------|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(E)----- Access Token ------>|    Resource   |
     |        |                               |     Server    |
     |        |<-(F)--- Protected Resource ---|               |
     +--------+                               +---------------+

                     Figure: Abstract Protocol Flow

figure from : https://tools.ietf.org/html/rfc6749#page-7

  • A: Client端向resource owner發送授權的request。這個授權request可以直接向resource owner發送,或是由authorization server來發送request。
  • B: Client取得resource owner的authorization grant(授權許可)。這個許可,可以用來代表resource owner的授權。
  • C: Client端向authorization server請求access token,這時client端要認證自己,並給予從resource owner那邊取得的授權許可。
  • D: Authorization server在認證client端後,在驗證經由client端所傳來的授權許可。若兩者皆合法,就會簽發給client端access token。
  • E: Client端將由authorization server所得到access token傳在request中,向resource server來取得protected resource(受保護資料)。
  • F: Resource server驗證來自client端傳來的access token,若合法,就回傳受保護資料給client端。

在這邊所提及的access token,我們可以把它當作是使用者憑證。當從authorization server取得後,就能透過該憑證來跟resource server取得該使用者的受保護資料。

Facebook

在Facebook中,它所處理的OAuth2的流程大致上是:

     +--------+                               +---------------+
     |        |--(A)- Authorization Request ->|   Resource    |
     |        |                               |     Owner     |
     |        |<-(B)-- Authorization Grant ---|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(C)-- Authorization Grant -->| Authorization |
     | Client |                               |     Server    |
     |        |<-(D)----- Access Token -------|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(E)----- Access Token ------>|    Resource   |
     |        |                               |     Server    |
     |        |<-(F)--- Protected Resource ---|               |
     +--------+                               +---------------+

                     Figure: Facebook Protocol Flow

figure from : https://tools.ietf.org/html/rfc6749#page-7

可以發現到,其實跟OAuth文件中,所提出來的概念流程沒什麼差異(幾乎一模一樣)。

  • A: Client(第三方)將resource owner(使用者)的畫面導至Facebook認證頁。如下圖所示:

figure from: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow/

登入動作可由下述Facebook提供的 API來呼叫:

https://www.facebook.com/v2.10/dialog/oauth?
  client_id={app-id}
  &redirect_uri={redirect-uri}
  &scope=email

註記:

  • client_id: 申請facebook app所給予的app id。
  • redirect_uri: 當使用者按下確定給予權限許可後,所導入的uri。
    (其uri設定需要與facebook app中的「有效的 OAuth 重新導向 URI」一致)
  • scope: 第三方向使用者要求的權限。(例子中為第三方想向使用者提取email資料)
    *scope為非必要欄位,但若是要取得使用者特定資料就得設定。
  • B: 當resource owner按下確認按鈕後,就會將要取得的grant導向到上述API所設定的redirect_uri。

而Facebook就會將grant放置到所設定的redirect_uri上。假設我們設定的redirect_uri為:https://test.com 。則:

https://test.com/?code=...

code後面…的內容就是我們所收到的grant。

  • C: Client端要向authorization server來索取access token。

我們可以使用下述的Facebook所提供的API來呼叫:

GET https://graph.facebook.com/v2.10/oauth/access_token?
   client_id={app-id}
   &redirect_uri={redirect-uri}
   &client_secret={app-secret}
   &code={code-parameter}

註記:

  • client-id: 申請facebook app所給予的app id。
  • redirect-uri: 當使用者按下確定給予權限許可後,所導入的頁面。
  • client-secret: 申請facebook app所給予的金鑰。
  • code: 由「登入」動作重新導向後所得的參數(grant)。
  • D: Authorization server開始驗證client端的身份及驗證grant。若合法,會將access token傳入上述API所設定的redirect_uri中。

在C動作的API response為:

{
  "access_token": {access-token}, 
  "token_type": {type},
  "expires_in":  {seconds-til-expiration}
}

註記:expires_in: 為access_token存活的時間。

  • E: 這時client就可以將透過access token來跟resource server索取resource owner受保護的資料。

  • F: 當驗證client端所傳過來的access token為合法後,就可以取得resource owner受保護的資料。

提取resource owner的受保護資料部份在facebook graph API的文件中,並沒有完整的範例。因此,這邊筆者就先不解釋facebook graph API的處理步驟。

若是讀者們對於網頁、IOS、Andrioid或其他裝置,讀者可進一步的參考這份文件。對於特定程式語言或平台,Facebook有提供SDK能更快的協助開發。

註記:這部分可參考Facebook Login - Documentation - Facebook for Developers

小結

簡單來說,要是今天我們所開發的系統需要做一個會員系統,但是又不想額外在耗費時間及人力成本的情況下,可以嘗試做一個OAuth2的登入方式。

筆者覺得若是能藉由各大知名OAuth2來做登入,或多或少也能吸引些使用者進行註冊。這是因為使用者們不用為了要加入成為一個新會員,又去填寫些個人資料、收認證信、手機認證…等。繁瑣步驟。

但若是該系統需要使用者更進一步的個人資料,如購物車網站、銀行…等。就還是得要自行開發一個屬於自家企家(公司)的會員系統。

概念的部分就告一段落,下一篇我們將透過Node.js來實作一個第三方登入。

參考資料

RFC 6749-The OAuth 2.0 Authorization Framework

Manually Build a Login Flow - Facebook Login - Documentation - Facebook for Developers

OAuth - 维基百科


上一篇
Node.js-Backend見聞錄(25):關於Server建置
下一篇
Node.js-Backend見聞錄(27):進階實作-關於第三方登入(二)
系列文
Node JS-Back end見聞錄31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言